import { ref, reactive, computed, watch, nextTick } from 'vue'
import { ElMessage } from 'element-plus'

// 缓存项接口
interface CacheItem<T = any> {
  data: T
  timestamp: number
  expiry?: number
  version?: string
  tags?: string[]
}

// 缓存配置接口
interface CacheConfig {
  defaultExpiry?: number // 默认过期时间（毫秒）
  maxSize?: number // 最大缓存项数
  storageType?: 'memory' | 'localStorage' | 'sessionStorage'
  keyPrefix?: string // 键前缀
  enableCompression?: boolean // 是否启用压缩
}

// 缓存统计接口
interface CacheStats {
  hits: number
  misses: number
  sets: number
  deletes: number
  clears: number
  hitRate: number
}

// 默认配置
const DEFAULT_CONFIG: Required<CacheConfig> = {
  defaultExpiry: 30 * 60 * 1000, // 30分钟
  maxSize: 100,
  storageType: 'memory',
  keyPrefix: 'app_cache_',
  enableCompression: false
}

// 内存缓存存储
const memoryCacheStore = reactive<Map<string, CacheItem>>(new Map())

// 缓存统计
const cacheStats = reactive<CacheStats>({
  hits: 0,
  misses: 0,
  sets: 0,
  deletes: 0,
  clears: 0,
  hitRate: 0
})

// 缓存管理 Composable
export const useCache = (config: CacheConfig = {}) => {
  const finalConfig = { ...DEFAULT_CONFIG, ...config }
  
  // 获取完整键名
  const getFullKey = (key: string): string => {
    return `${finalConfig.keyPrefix}${key}`
  }
  
  // 检查是否过期
  const isExpired = (item: CacheItem): boolean => {
    if (!item.expiry) return false
    return Date.now() > item.timestamp + item.expiry
  }
  
  // 更新统计信息
  const updateStats = () => {
    const total = cacheStats.hits + cacheStats.misses
    cacheStats.hitRate = total > 0 ? (cacheStats.hits / total) * 100 : 0
  }
  
  // 压缩数据（简单的JSON压缩）
  const compressData = (data: any): string => {
    if (!finalConfig.enableCompression) {
      return JSON.stringify(data)
    }
    // 这里可以集成更复杂的压缩算法
    return JSON.stringify(data)
  }
  
  // 解压数据
  const decompressData = (data: string): any => {
    try {
      return JSON.parse(data)
    } catch {
      return null
    }
  }
  
  // 内存缓存操作
  const memoryOperations = {
    get: (key: string): CacheItem | null => {
      const item = memoryCacheStore.get(key)
      if (!item) return null
      
      if (isExpired(item)) {
        memoryCacheStore.delete(key)
        return null
      }
      
      return item
    },
    
    set: (key: string, item: CacheItem): void => {
      // 检查缓存大小限制
      if (memoryCacheStore.size >= finalConfig.maxSize && !memoryCacheStore.has(key)) {
        // 删除最旧的项
        const oldestKey = memoryCacheStore.keys().next().value
        if (oldestKey) {
          memoryCacheStore.delete(oldestKey)
        }
      }
      
      memoryCacheStore.set(key, item)
    },
    
    delete: (key: string): boolean => {
      return memoryCacheStore.delete(key)
    },
    
    clear: (): void => {
      memoryCacheStore.clear()
    },
    
    keys: (): string[] => {
      return Array.from(memoryCacheStore.keys())
    },
    
    size: (): number => {
      return memoryCacheStore.size
    }
  }
  
  // 本地存储操作
  const storageOperations = {
    get: (key: string): CacheItem | null => {
      if (typeof window === 'undefined') return null
      
      try {
        const storage = finalConfig.storageType === 'localStorage' ? localStorage : sessionStorage
        const data = storage.getItem(getFullKey(key))
        if (!data) return null
        
        const item: CacheItem = decompressData(data)
        if (!item) return null
        
        if (isExpired(item)) {
          storage.removeItem(getFullKey(key))
          return null
        }
        
        return item
      } catch (error) {
        console.error('缓存读取失败:', error)
        return null
      }
    },
    
    set: (key: string, item: CacheItem): void => {
      if (typeof window === 'undefined') return
      
      try {
        const storage = finalConfig.storageType === 'localStorage' ? localStorage : sessionStorage
        const data = compressData(item)
        storage.setItem(getFullKey(key), data)
      } catch (error) {
        console.error('缓存写入失败:', error)
        // 如果存储空间不足，尝试清理过期项
        if (error instanceof DOMException && error.code === 22) {
          storageOperations.clearExpired()
          try {
            const storage = finalConfig.storageType === 'localStorage' ? localStorage : sessionStorage
            const data = compressData(item)
            storage.setItem(getFullKey(key), data)
          } catch {
            ElMessage.warning('存储空间不足，缓存写入失败')
          }
        }
      }
    },
    
    delete: (key: string): boolean => {
      if (typeof window === 'undefined') return false
      
      try {
        const storage = finalConfig.storageType === 'localStorage' ? localStorage : sessionStorage
        storage.removeItem(getFullKey(key))
        return true
      } catch (error) {
        console.error('缓存删除失败:', error)
        return false
      }
    },
    
    clear: (): void => {
      if (typeof window === 'undefined') return
      
      try {
        const storage = finalConfig.storageType === 'localStorage' ? localStorage : sessionStorage
        const keys = Object.keys(storage).filter(key => key.startsWith(finalConfig.keyPrefix))
        keys.forEach(key => storage.removeItem(key))
      } catch (error) {
        console.error('缓存清理失败:', error)
      }
    },
    
    clearExpired: (): void => {
      if (typeof window === 'undefined') return
      
      try {
        const storage = finalConfig.storageType === 'localStorage' ? localStorage : sessionStorage
        const keys = Object.keys(storage).filter(key => key.startsWith(finalConfig.keyPrefix))
        
        keys.forEach(key => {
          try {
            const data = storage.getItem(key)
            if (data) {
              const item: CacheItem = decompressData(data)
              if (item && isExpired(item)) {
                storage.removeItem(key)
              }
            }
          } catch {
            // 如果解析失败，删除该项
            storage.removeItem(key)
          }
        })
      } catch (error) {
        console.error('过期缓存清理失败:', error)
      }
    },
    
    keys: (): string[] => {
      if (typeof window === 'undefined') return []
      
      try {
        const storage = finalConfig.storageType === 'localStorage' ? localStorage : sessionStorage
        return Object.keys(storage)
          .filter(key => key.startsWith(finalConfig.keyPrefix))
          .map(key => key.replace(finalConfig.keyPrefix, ''))
      } catch (error) {
        console.error('获取缓存键失败:', error)
        return []
      }
    },
    
    size: (): number => {
      return storageOperations.keys().length
    }
  }
  
  // 选择操作方法
  const operations = finalConfig.storageType === 'memory' ? memoryOperations : storageOperations
  
  // 获取缓存
  const get = <T = any>(key: string): T | null => {
    const item = operations.get(key)
    
    if (item) {
      cacheStats.hits++
      updateStats()
      return item.data as T
    } else {
      cacheStats.misses++
      updateStats()
      return null
    }
  }
  
  // 设置缓存
  const set = <T = any>(
    key: string, 
    data: T, 
    options: {
      expiry?: number
      version?: string
      tags?: string[]
    } = {}
  ): void => {
    const item: CacheItem<T> = {
      data,
      timestamp: Date.now(),
      expiry: options.expiry ?? finalConfig.defaultExpiry,
      version: options.version,
      tags: options.tags
    }
    
    operations.set(key, item)
    cacheStats.sets++
    updateStats()
  }
  
  // 删除缓存
  const remove = (key: string): boolean => {
    const result = operations.delete(key)
    if (result) {
      cacheStats.deletes++
      updateStats()
    }
    return result
  }
  
  // 检查是否存在
  const has = (key: string): boolean => {
    return get(key) !== null
  }
  
  // 清空缓存
  const clear = (): void => {
    operations.clear()
    cacheStats.clears++
    updateStats()
  }
  
  // 根据标签删除
  const removeByTag = (tag: string): number => {
    let count = 0
    const keys = operations.keys()
    
    keys.forEach(key => {
      const item = operations.get(key)
      if (item?.tags?.includes(tag)) {
        if (operations.delete(key)) {
          count++
        }
      }
    })
    
    if (count > 0) {
      cacheStats.deletes += count
      updateStats()
    }
    
    return count
  }
  
  // 根据版本删除
  const removeByVersion = (version: string): number => {
    let count = 0
    const keys = operations.keys()
    
    keys.forEach(key => {
      const item = operations.get(key)
      if (item?.version === version) {
        if (operations.delete(key)) {
          count++
        }
      }
    })
    
    if (count > 0) {
      cacheStats.deletes += count
      updateStats()
    }
    
    return count
  }
  
  // 清理过期项
  const clearExpired = (): number => {
    if (finalConfig.storageType === 'memory') {
      let count = 0
      const keys = Array.from(memoryCacheStore.keys())
      
      keys.forEach(key => {
        const item = memoryCacheStore.get(key)
        if (item && isExpired(item)) {
          memoryCacheStore.delete(key)
          count++
        }
      })
      
      if (count > 0) {
        cacheStats.deletes += count
        updateStats()
      }
      
      return count
    } else {
      storageOperations.clearExpired()
      return 0 // 无法准确统计存储清理的数量
    }
  }
  
  // 获取所有键
  const keys = (): string[] => {
    return operations.keys()
  }
  
  // 获取缓存大小
  const size = (): number => {
    return operations.size()
  }
  
  // 获取缓存信息
  const getInfo = (key: string) => {
    const item = operations.get(key)
    if (!item) return null
    
    return {
      key,
      timestamp: item.timestamp,
      expiry: item.expiry,
      version: item.version,
      tags: item.tags,
      isExpired: isExpired(item),
      age: Date.now() - item.timestamp
    }
  }
  
  // 批量操作
  const mget = <T = any>(keys: string[]): Record<string, T | null> => {
    const result: Record<string, T | null> = {}
    keys.forEach(key => {
      result[key] = get<T>(key)
    })
    return result
  }
  
  const mset = <T = any>(
    items: Record<string, T>, 
    options: {
      expiry?: number
      version?: string
      tags?: string[]
    } = {}
  ): void => {
    Object.entries(items).forEach(([key, data]) => {
      set(key, data, options)
    })
  }
  
  const mremove = (keys: string[]): number => {
    let count = 0
    keys.forEach(key => {
      if (remove(key)) {
        count++
      }
    })
    return count
  }
  
  // 缓存装饰器
  const cached = <T extends (...args: any[]) => any>(
    fn: T,
    options: {
      keyGenerator?: (...args: Parameters<T>) => string
      expiry?: number
      version?: string
      tags?: string[]
    } = {}
  ) => {
    const keyGenerator = options.keyGenerator || ((...args) => `fn_${fn.name}_${JSON.stringify(args)}`)
    
    return ((...args: Parameters<T>): ReturnType<T> => {
      const key = keyGenerator(...args)
      let result = get<ReturnType<T>>(key)
      
      if (result === null) {
        result = fn(...args)
        set(key, result, {
          expiry: options.expiry,
          version: options.version,
          tags: options.tags
        })
      }
      
      return result as ReturnType<T>
    }) as T
  }
  
  // 异步缓存装饰器
  const cachedAsync = <T extends (...args: any[]) => Promise<any>>(
    fn: T,
    options: {
      keyGenerator?: (...args: Parameters<T>) => string
      expiry?: number
      version?: string
      tags?: string[]
    } = {}
  ) => {
    const keyGenerator = options.keyGenerator || ((...args) => `async_fn_${fn.name}_${JSON.stringify(args)}`)
    
    return (async (...args: Parameters<T>): Promise<Awaited<ReturnType<T>>> => {
      const key = keyGenerator(...args)
      let result = get<Awaited<ReturnType<T>>>(key)
      
      if (result === null) {
        result = await fn(...args)
        set(key, result, {
          expiry: options.expiry,
          version: options.version,
          tags: options.tags
        })
      }
      
      return result as Awaited<ReturnType<T>>
    }) as T
  }
  
  return {
    // 基本操作
    get,
    set,
    remove,
    has,
    clear,
    
    // 高级操作
    removeByTag,
    removeByVersion,
    clearExpired,
    
    // 信息获取
    keys,
    size,
    getInfo,
    
    // 批量操作
    mget,
    mset,
    mremove,
    
    // 装饰器
    cached,
    cachedAsync,
    
    // 统计信息
    stats: computed(() => ({ ...cacheStats })),
    
    // 配置信息
    config: computed(() => ({ ...finalConfig }))
  }
}

// 创建默认缓存实例
export const defaultCache = useCache()

// 创建特定类型的缓存实例
export const createCache = (config: CacheConfig) => useCache(config)

// 内存缓存实例
export const memoryCacheInstance = useCache({ storageType: 'memory' })

// 本地存储缓存实例
export const localCache = useCache({ storageType: 'localStorage' })

// 会话存储缓存实例
export const sessionCache = useCache({ storageType: 'sessionStorage' })

// 导出类型
export type { CacheItem, CacheConfig, CacheStats }